#include "C_BaseMaterial.h"
#include <stdio.h>
#include <string.h>

void						BaseMaterial(S_BaseMaterial &material)
{
	material.ambient = f4();
	material.diffuse = f4();
	material.specular = f4();
	material.emission = f4();
	material.shininess = 0.0f;
}

void						BaseMaterial(S_BaseMaterial	&material, 
														 const float4		&ambient, 
														 const float4		&diffuse, 
														 const float4		&specular, 
														 const float4		&emission, 
														 float					 shininess)
{
	material.ambient = ambient;
	material.diffuse = diffuse;
	material.specular = specular;
	material.emission = emission;
	material.shininess = shininess;
}

S_BaseMaterial *BaseMaterial(S_BaseMaterial *pMaterial)
{
#ifdef _DEBUG
	if (pMaterial == NULL) return NULL;
#endif

	pMaterial->ambient = f4();
	pMaterial->diffuse = f4();
	pMaterial->specular = f4();
	pMaterial->emission = f4();
	pMaterial->shininess = 0.0f;

	return pMaterial;
}

S_BaseMaterial *BaseMaterial(S_BaseMaterial *pMaterial, 
														 const float4		&ambient, 
														 const float4		&diffuse, 
														 const float4		&specular, 
														 const float4		&emission, 
														 float					 shininess)
{
#ifdef _DEBUG
	if (pMaterial == NULL) return NULL;
#endif

	pMaterial->ambient = ambient;
	pMaterial->diffuse = diffuse;
	pMaterial->specular = specular;
	pMaterial->emission = emission;
	pMaterial->shininess = shininess;

	return pMaterial;
}

const char * C_BaseMaterial::m_Type = "BaseMaterial";

C_BaseMaterial::C_BaseMaterial(void)
{
	BaseMaterial(m_BaseMaterial);

	//m_Type = "BaseMaterial";
}

C_BaseMaterial::C_BaseMaterial(const float4		&ambient, 
															 const float4		&diffuse, 
															 const float4		&specular, 
															 const float4		&emission, 
															 float					 shininess)
{
	BaseMaterial(m_BaseMaterial, ambient, diffuse, specular, emission, shininess);
}

C_BaseMaterial::~C_BaseMaterial(void)
{
}

bool C_BaseMaterial::processElement(const char *elementName, 
																		NxI32 argc, 
																		const char **argv, 
																		const char *elementData, 
																		NxI32 lineno)
{
	if (strcmp(elementName, "Material") == 0)
	{
		if ((argc != 2) || strcmp(argv[0], "type") != 0 || strcmp(argv[1], m_Type) != 0 )
			return false;
	}

	if (strcmp(elementName, STRING_V_AMBIENT) == 0)
	{
		float x, y, z, w;
		sscanf(elementData, "%f%f%f%f", &x, &y, &z, &w);
		m_BaseMaterial.ambient = f4(x, y, z, w);
	}

	if (strcmp(elementName, STRING_V_DIFFUSE) == 0)
	{
		float x, y, z, w;
		sscanf(elementData, "%f%f%f%f", &x, &y, &z, &w);
		m_BaseMaterial.diffuse = f4(x, y, z, w);
	}

	if (strcmp(elementName, STRING_V_SPECULAR) == 0)
	{
		float x, y, z, w;
		sscanf(elementData, "%f%f%f%f", &x, &y, &z, &w);
		m_BaseMaterial.specular = f4(x, y, z, w);
	}

	if (strcmp(elementName, STRING_V_EMISSION) == 0)
	{
		float x, y, z, w;
		sscanf(elementData, "%f%f%f%f", &x, &y, &z, &w);
		m_BaseMaterial.emission = f4(x, y, z, w);
	}

	if (strcmp(elementName, STRING_V_SHININESS) == 0)
	{
		float s;
		sscanf(elementData, "%f", &s);
		m_BaseMaterial.shininess = s;
	}

	return true;
}

bool C_BaseMaterial::serialize(const char * fileName)
{
	FILE * f = fopen(fileName, "w");
	if (f == NULL) return false;

	fprintf(f, "<?xml version=""1.0""?>\n");

	fprintf(f, "\t<Material type=\"%s\">\n", m_Type);
		fprintf(f, "\t\t<BaseMaterial>\n");

			fprintf(f, "\t\t\t<%s>\n", STRING_V_AMBIENT);
				fprintf(f, "\t\t\t\t%f %f %f %f\n",  m_BaseMaterial.ambient.x, 
																						 m_BaseMaterial.ambient.y, 
																						 m_BaseMaterial.ambient.z, 
																						 m_BaseMaterial.ambient.w);
			fprintf(f, "\t\t\t<\\%s>\n", STRING_V_AMBIENT);

			fprintf(f, "\t\t\t<%s>\n", STRING_V_DIFFUSE);
				fprintf(f, "\t\t\t\t%f %f %f %f\n",  m_BaseMaterial.diffuse.x, 
																						 m_BaseMaterial.diffuse.y, 
																						 m_BaseMaterial.diffuse.z, 
																						 m_BaseMaterial.diffuse.w);
			fprintf(f, "\t\t\t<\\%s>\n", STRING_V_DIFFUSE);

			fprintf(f, "\t\t\t<%s>\n", STRING_V_SPECULAR);
				fprintf(f, "\t\t\t\t%f %f %f %f\n",  m_BaseMaterial.specular.x, 
																						 m_BaseMaterial.specular.y, 
																						 m_BaseMaterial.specular.z, 
																						 m_BaseMaterial.specular.w);
			fprintf(f, "\t\t\t<\\%s>\n", STRING_V_SPECULAR);

			fprintf(f, "\t\t\t<%s>\n", STRING_V_EMISSION);
				fprintf(f, "\t\t\t\t%f %f %f %f\n",  m_BaseMaterial.emission.x, 
																						 m_BaseMaterial.emission.y, 
																						 m_BaseMaterial.emission.z, 
																						 m_BaseMaterial.emission.w);
			fprintf(f, "\t\t\t<\\%s>\n", STRING_V_EMISSION);

			fprintf(f, "\t\t\t<%s>\n", STRING_V_SHININESS);
				fprintf(f, "\t\t\t\t%f\n", m_BaseMaterial.shininess);
			fprintf(f, "\t\t\t<\\%s>\n", STRING_V_SHININESS);

		fprintf(f, "\t\t<\\BaseMaterial>\n");
	fprintf(f, "\t<\\Material>\n");

	fclose(f);

	return true;
}

bool C_BaseMaterial::deserialize(const char * fileName)
{
	NVSHARE::FastXml *pXml = NVSHARE::createFastXml();

	bool result = pXml->processXmlFile(fileName, this);

	NVSHARE::releaseFastXml(pXml);

	return result;
}